-- the local upvalues bandwagon
local select = select
local UnitClass = UnitClass
local UnitIsDead = UnitIsDead
local UnitIsGhost = UnitIsGhost
local UnitIsPlayer = UnitIsPlayer
local UnitReaction = UnitReaction
local UnitIsConnected = UnitIsConnected
local UnitReactionColor = UnitReactionColor
local RAID_CLASS_COLORS = RAID_CLASS_COLORS
local UnitLevel = UnitLevel
local UnitIsTapped = UnitIsTapped
local UnitIstappedByPlayer = UnitIsTappedByPlayer
local UnitPowerType = UnitPowerType
local UnitClassification = UnitClassification
local UnitCreatureFamily = UnitCreatureFamily
local UnitCreatureType = UnitCreatureType
local UnitCanAttack = UnitCanAttack

local core = oUF.Jerry

local backdrop = core.backdrop
local statusbartexture = core.statusbartexture

-- colors
local powercolor = core.powercolor
local gray = core.gray
local white = core.white
local unknown = core.unknown

local classificationFormats = core.classificationFormats
local getDifficultyColor = core.getDifficultyColor
local auraIcon = core.auraIcon
local OnEnter, OnLeave = core.OnEnter, core.OnLeave
local getFontString = core.getFontString
local styleClicks = core.styleClicks
local styleCombatFeedback = core.styleCombatFeedback

local function updateLevel(self, event, unit)
	if self.unit ~= unit then return end

	local lvl = self.Lvl
	local level = UnitLevel(unit)
	local classification = UnitClassification(unit)

	if classificationFormats[classification] then
		lvl:SetFormattedText(classificationFormats[classification], level)
	else
		lvl:SetText(level)
	end

	if UnitCanAttack("player", unit) then
		lvl:SetTextColor(getDifficultyColor(level))
	else
		lvl:SetTextColor(1, 1, 1)
	end
end

local function updateName(self, event, unit)
	if self.unit ~= unit then return end

	self.Name:SetText(UnitName(unit))
	updateLevel(self, event, unit)

	local color
	if UnitIsPlayer(unit)  then
		local class, rclass = UnitClass(unit)
		self.Class:SetText(class)
		color = RAID_CLASS_COLORS[rclass]
	else
		self.Class:SetText(UnitCreatureFamily(unit) or UnitCreatureType(unit))
	end
	if not color then color = white end
	self.Class:SetVertexColor(color.r, color.g, color.b)
	self.Race:SetText(UnitRace(unit))
end

local MH = LibStub("LibMobHealth-4.0")

local function updateHealth(self, event, bar, unit, min, max)
	local rmin, rmax = MH:GetUnitHealth(unit)

	if UnitIsDead(unit) then
		bar:SetValue(0)
		bar.value:SetText("Dead")
	elseif UnitIsGhost(unit) then
		bar:SetValue(0)
		bar.value:SetText("Ghost")
	elseif not UnitIsConnected(unit) then
		bar:SetValue(0)
		bar.value:SetText("Offline")
	else
		if max > 100 then
			min = min * 100 / max
		end
		bar.value:SetFormattedText("%d%% %d/%d", min, rmin, rmax)
	end

	local color
	if UnitIsPlayer(unit) then
		color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
	elseif UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) and not UnitIsPlayer(unit) then
		color = gray
	else
		color = UnitReactionColor[UnitReaction(unit, "player")]
	end
	if not color then
		color = unknown
	end
	bar:SetStatusBarColor(color.r, color.g, color.b)
	bar.bg:SetTexture(color.r, color.g, color.b, .25)
end


local function updatePower(self, event, bar, unit, min, max)
	if max == 0 or UnitIsDead(unit) or UnitIsGhost(unit) or not UnitIsConnected(unit) then
		bar:SetValue(0)
		bar.value:SetText()
	else
		bar.value:SetFormattedText("%d%% %d/%d", floor(min/max*100), min, max)
	end

	local color = powercolor(unit)
	bar:SetStatusBarColor(color.r, color.g, color.b)
	bar.bg:SetTexture(color.r, color.g, color.b, 0.25)
end

local function setStyle(settings, self, unit)
	styleClicks(self, TargetFrameDropDown)

	-- Background
	self:SetBackdrop(backdrop)
	self:SetBackdropColor(0,0,0,1)

	-- Healthbar
	local hp = CreateFrame("StatusBar", nil, self)
	hp:SetHeight(22) -- 16 height if we're dealing with tiny or micro frames
	hp:SetStatusBarTexture(statusbartexture)
	hp:SetPoint("TOPLEFT")
	hp:SetPoint("TOPRIGHT")

	-- Healthbar background
	hp.bg = hp:CreateTexture(nil, "BORDER")
	hp.bg:SetAllPoints(hp)
	hp.bg:SetTexture(.25,.25,.25)

	-- Healthbar text
	hp.value = getFontString(hp)
	hp.value:SetPoint("RIGHT", -2, -1)

	self.Health = hp
	self.OverrideUpdateHealth = updateHealth

	local icon = hp:CreateTexture(nil, "OVERLAY")
	icon:SetHeight(16)
	icon:SetWidth(16)
	icon:SetPoint("TOP", self, 0, 8)
	icon:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons")
	self.RaidIcon = icon

	self.Name = getFontString(hp)
	self.Name:SetPoint("LEFT", 2, -1)
	self.UNIT_NAME_UPDATE = updateName

	-- Power Bar
	local pp = CreateFrame("StatusBar", nil, self)
	pp:SetHeight(16)
	pp:SetStatusBarTexture(statusbartexture)

	pp:SetPoint("LEFT")
	pp:SetPoint("RIGHT")
	pp:SetPoint("TOP", hp, "BOTTOM", 0, -1.35)

	local ppbg = pp:CreateTexture(nil, "BORDER")
	ppbg:SetAllPoints(pp)
	ppbg:SetTexture(.25,.25,.25)

	pp.bg = ppbg
	self.Power = pp
	self.OverrideUpdatePower = updatePower

	pp.value = getFontString(pp)
	pp.value:SetPoint("RIGHT", -2, 1)

	self.Lvl = getFontString(pp)
	self.Lvl:SetPoint("LEFT", pp, "LEFT", 2, 0)

	self.Class = getFontString(pp)
	self.Class:SetPoint("LEFT", self.Lvl, "RIGHT",  1, 0)

	self.Race = getFontString(pp)
	self.Race:SetPoint("LEFT", self.Class, "RIGHT",  1, 0)

	-- player, pet party and partypets get debuff highlighting
	self.DebuffHighlightBackdrop = true -- oUF_DebuffHighlight Support, using the backdrop
	self.DebuffHighlightFilter = true -- only show debuffs I can cure

	styleCombatFeedback(self)

	local auras = CreateFrame("Frame", nil, self)
	auras.size = 26
	auras:SetHeight(auras.size)
	auras:SetWidth(auras.size*16)
	auras:SetPoint("TOPLEFT", self, "TOPRIGHT",5,0)
	auras.initialAnchor = "TOPLEFT"
	auras["growth-y"] = "DOWN"
	auras["growth-x"] = "RIGHT"
	self.Auras = auras

	local playerClass = select(2, UnitClass("player")) -- combopoints for druid/rogue
	if playerClass == "ROGUE" or playerClass == "DRUID" then
		self.CPoints = getFontString(self)
		self.CPoints:SetPoint("BOTTOMRIGHT", self, "TOPRIGHT", -2, 4)
		self.CPoints:SetFont("Interface\\AddOns\\oUF_Jerry\\media\\barframes.ttf", 38, "OUTLINE")
		self.CPoints:SetJustifyH("RIGHT")
	end

	local cb = CreateFrame("StatusBar", nil, self)
	cb:SetHeight(10)
	cb:SetStatusBarTexture(statusbartexture)
	cb:SetStatusBarColor(1, 1, 0)

	cb:SetPoint("LEFT", 10, 0)
	cb:SetPoint("RIGHT")
	cb:SetPoint("TOP", pp, "BOTTOM", 0, -1.35)

	local cbbg = cb:CreateTexture(nil, "BORDER")
	cbbg:SetAllPoints(cb)
	cbbg:SetTexture(.25,.25,.25)
	cb.bg = cbbg

	local cbtxt = getFontString(cb)
	cbtxt:SetPoint("LEFT", 2, 0)
	cb.text = cbtxt

	local cbicon = cb:CreateTexture(nil, "OVERLAY")
	cbicon:SetWidth(10)
	cbicon:SetHeight(10)
	cbicon:SetPoint("LEFT", -10, 0)
	cb.icon = cbicon
	self.Castbar = cb
	self.castbarRefreshRate = 0

	self.PostCreateAuraIcon = auraIcon

	return self
end

local target = oUF:Spawn("target", "oUF_Target", {
	["initial-width"] = 320,
	["initial-height"] = 49,
	setup = setStyle,
})
target:SetPoint("TOPLEFT", oUF_Player, "TOPRIGHT", 20, 0)
